package com.utilities.pipelineScripts;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import com.utilities.IO.FileUtilities;
import com.utilities.dataStructures.Range;
import com.utilities.fastaUtilities.MummerUtilities;
import com.utilities.fastaUtilities.OtherUtilities;
import com.utilities.parsers.ContigParser.ParseAllContigsFileParser;
import com.utilities.parsers.ContigParser.ParseEvents;
import com.utilities.parsers.ContigParser.ParseListener;

public class MapperUtilities {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception 
	{
		int option = Integer.parseInt(args[0]);
		switch (option)
		{
			case 0:
			{
				/*
				 * showtiling output
				 * contigs fetched
				 * contigs not found
				 * initial contigs file
				 * coords file
				 * not aligned contigs list
				 * excluded contigs list
				 * excluded contigs file
				 * included contings file     
				 * not aligned contigs file    
				 * refSeqSize file
				 */
				BufferedReader bufferedReader = new BufferedReader(new FileReader(args[11]));
				String readLine = bufferedReader.readLine();
				if (readLine == null) 
				{
					System.out.println("Cannot read the seq length from " + args[11]);
					bufferedReader.close();
					return;
				}
				bufferedReader.close();
				
				String[] params = new String[4];
				params[0] = args[1];
				params[1] = args[5];
				params[2] = args[4];
				// refSeqSize
				params[3] = readLine;
				MummerUtilities mummerUtilities = new MummerUtilities();
				ArrayList<ArrayList<Range>> lists =
				mummerUtilities.getIncludedExcludedAndNotAlignedContigRanges(params);
				// write just the metadata
				FileUtilities.WriteToFile(lists.get(0), args[7],2);
				FileUtilities.WriteToFile(lists.get(1), args[6],2);
				
				params = new String[6];
				params[0] = args[4];
				params[1] = args[1];
				params[2] = args[8];
				params[3] = args[10];
				params[4] = args[5];
				params[5] = args[9];	
				MapperUtilities mapperUtilities = new MapperUtilities();
				mapperUtilities.writeIncludedExcludedAndNotAlignedContigs(params);
				break;
			}
			case 1:
			{
				String[] params = new String[3];
				// contigs fetched file
				params[0] = args[1];
				// contigs file
				params[1] = args[2];
				// contigsRearranged file
				params[2] = args[3];
				OtherUtilities otherUtilities2 = new OtherUtilities();
				otherUtilities2.reArrangeContigs(params);
				break;
			}
		}
	}
	
	/**
	 * @param args
	 * args[0] = all contigs file
	 * args[1] = tiling file
	 * args[2] = excluded contigs file
	 * args[3] = not aligned contigs file
	 * args[4] = coords file
	 * args[5] = included contigs file
	 */
	private void writeIncludedExcludedAndNotAlignedContigs(String[] args)
	{
		try
		{
			ParseAllContigsFileParser allContigsFileParser = new ParseAllContigsFileParser();
			Handler handler = new Handler().setExcludedContigsWriter(args[2])
			.setNotAlignedContigsWriter(args[3]).setContigsListFromTiling(args[1], args[4])
			.setIncludedContigsWriter(args[5]);
			allContigsFileParser.addListener(handler);
			allContigsFileParser.parse(new FileReader(args[0]));
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	
	
	private class Handler extends ParseListener
	{
		PrintWriter excludedWriter = null;
		PrintWriter notAlignedWriter = null;
		PrintWriter includedAlignedWriter = null;
		ArrayList<String> contigsListFromTiling = null;
		ArrayList<String> excludedListFromTiling = null;
		boolean flag_notAligned = true;
		boolean skip = true;
		@Override
		public void handleEvent(ParseEvents event) {
			String readLine = null;
			switch((ParseEvents.EventTypes)event.getEventType())
			{
			case contigStarted:
				readLine = ((String)event.getSource()).trim();
				String contigName = readLine.split(" ")[0].substring(1);
				if (!contigsListFromTiling.contains(contigName))
				{
					if (!excludedListFromTiling.contains(contigName))
					{
						flag_notAligned = true;
						skip = false;
						notAlignedWriter.println(readLine);
					}
					else
					{
						flag_notAligned = false;
						skip = false;
						excludedWriter.println(readLine);
					}
				}
				else
				{
					skip = true;
					includedAlignedWriter.println(readLine);
				}
				break;
			case docStarted:
				break;
			case docEnded:
				notAlignedWriter.flush();
				notAlignedWriter.close();
				excludedWriter.flush();
				excludedWriter.close();
				includedAlignedWriter.flush();
				includedAlignedWriter.close();
				break;
			case seqread:
				readLine = ((String)event.getSource()).trim();
				if (!skip)
				{
					if (flag_notAligned)
					{
						notAlignedWriter.println(readLine);
					}
					else
					{
						excludedWriter.println(readLine);
					}
				}
				else
				{
					includedAlignedWriter.println(readLine);
				}
				break;
			}	
		}
		
		public Handler setContigsListFromTiling(String tilingFile, String coordsFile) throws IOException 
		{
			ArrayList<ArrayList<String>> lsts = MummerUtilities.getTiledAndExcludedContigs(tilingFile,coordsFile);
			if (lsts != null && lsts.size() == 2)
			{
				this.contigsListFromTiling = lsts.get(0);
				this.excludedListFromTiling = lsts.get(1);
				return this;
			}
			else
				return null;
		}
		
		public Handler setIncludedContigsWriter(String includedContigsFile) throws FileNotFoundException
		{
			this.includedAlignedWriter = new PrintWriter(includedContigsFile);
			return this;
		}
		
		public Handler setExcludedContigsWriter(String excludedContigsFile) throws FileNotFoundException
		{
			this.excludedWriter = new PrintWriter(excludedContigsFile);
			return this;
		}
		public Handler setNotAlignedContigsWriter(String notAlignedContigsFile) throws FileNotFoundException
		{
			this.notAlignedWriter = new PrintWriter(notAlignedContigsFile);
			return this;
		}
	} // Handler
} // MapperUtilities
